package com.hcloud.libupload.utils

import com.hcloud.libupload.excetion.UploadError
import com.hcloud.libupload.request.UploadRequest
import okhttp3.internal.and
import java.io.*
import java.security.MessageDigest

class FileHash(val uploadRequest: UploadRequest) {
    private val mdSize = 1024 * 1024 * 5

    @Throws(Throwable::class)
    fun getFileMD5(file: File): String {
        if (!file.isFile) {
            return ""
        }
        val data: ByteArray = if (file.length() >= mdSize) {
            ByteArray(mdSize)
        } else {
            ByteArray(file.length().toInt())
        }
        val raf = RandomAccessFile(file, "r")
        raf.readFully(data, 0, data.size)
        var len = 0
        val digest: MessageDigest = MessageDigest.getInstance("MD5")
        val inputStream = FileInputStream(file)
        while (!uploadRequest.isCancel && inputStream.read(data, 0, data.size)
                .also { len = it } != -1
        ) {
            digest.update(data, 0, len)
        }
        inputStream.close()
        raf.close()
        if (uploadRequest.isCancel) {
            throw UploadError(
                UploadError.UPLOAD_ERROR_10005,
                "Canceled"
            )
        }
        return bytesToHexString(digest.digest())
    }

    @Throws(Throwable::class)
    fun getTestFileMD5(data: ByteArray): String? {
        val inputStream: InputStream
        var len = 0
        val digest: MessageDigest = MessageDigest.getInstance("MD5")
        inputStream = ByteArrayInputStream(data)
        while (!uploadRequest.isCancel && inputStream.read(data, 0, data.size)
                .also { len = it } != -1
        ) {
            digest.update(data, 0, len)
        }
        inputStream.close()
        if (uploadRequest.isCancel) {
            throw UploadError(
                UploadError.UPLOAD_ERROR_10005,
                "Canceled"
            )
        }
        return bytesToHexString(digest.digest())
    }

    @Throws(Throwable::class)
    private fun bytesToHexString(src: ByteArray): String {
        val stringBuilder = StringBuilder()
        if (src.isEmpty()) {
            return ""
        }
        for (i in src.indices) {
            if (uploadRequest.isCancel) {
                break
            }
            val v: Int = src[i] and 0xFF
            val hv = Integer.toHexString(v)
            if (hv.length < 2) {
                stringBuilder.append(0)
            }
            stringBuilder.append(hv)
        }
        if (uploadRequest.isCancel) {
            throw UploadError(
                UploadError.UPLOAD_ERROR_10005,
                "Canceled"
            )
        }
        return stringBuilder.toString()
    }

}